import Quill from 'quill';
import Delta from 'quill-delta';
import 'quill/dist/quill.snow.css';
import {
    walk,
    getTextFromHtml,
    isUndef,
    checkSmmFormatData,
    removeHtmlNodeByClass,
    formatGetNodeGeneralization,
    nodeRichTextToTextWithWrap,
} from '../utils';
import { CONSTANTS } from '../constants/constant';
import MindMapNode from '../core/render/node/MindMapNode';
import { Scope } from 'parchment';

let extended = false;

// 扩展quill的字体列表
let fontFamilyList = [
    '宋体, SimSun, Songti SC',
    '微软雅黑, Microsoft YaHei',
    '楷体, 楷体_GB2312, SimKai, STKaiti',
    '黑体, SimHei, Heiti SC',
    '隶书, SimLi',
    'andale mono',
    'arial, helvetica, sans-serif',
    'arial black, avant garde',
    'comic sans ms',
    'impact, chicago',
    'times new roman',
    'sans-serif',
    'serif',
];

// 扩展quill的字号列表
let fontSizeList = new Array(100).fill(0).map((_, index) => {
    return index + 'px';
});

// 富文本编辑插件
class RichText {
    constructor({ mindMap, pluginOpt }) {
        this.mindMap = mindMap;
        this.pluginOpt = pluginOpt;
        this.textEditNode = null;
        this.showTextEdit = false;
        this.quill = null;
        this.range = null;
        this.lastRange = null;
        this.pasteUseRange = null;
        this.node = null;
        this.isInserting = false;
        this.styleEl = null;
        this.cacheEditingText = '';
        this.lostStyle = false;
        this.isCompositing = false;
        this.textNodePaddingX = 6;
        this.textNodePaddingY = 4;
        this.initOpt();
        this.extendQuill();
        this.appendCss();
        this.bindEvent();

        // 处理数据，转成富文本格式
        if (this.mindMap.opt.data) {
            this.mindMap.opt.data = this.handleSetData(this.mindMap.opt.data);
        }
    }

    // 绑定事件
    bindEvent() {
        this.onCompositionStart = this.onCompositionStart.bind(this);
        this.onCompositionUpdate = this.onCompositionUpdate.bind(this);
        this.onCompositionEnd = this.onCompositionEnd.bind(this);
        window.addEventListener('compositionstart', this.onCompositionStart);
        window.addEventListener('compositionupdate', this.onCompositionUpdate);
        window.addEventListener('compositionend', this.onCompositionEnd);
    }

    // 解绑事件
    unbindEvent() {
        window.removeEventListener('compositionstart', this.onCompositionStart);
        window.removeEventListener(
            'compositionupdate',
            this.onCompositionUpdate,
        );
        window.removeEventListener('compositionend', this.onCompositionEnd);
    }

    // 插入样式
    appendCss() {
        this.mindMap.appendCss(
            'richText',
            `
      .smm-richtext-node-wrap {
        word-break: break-all;
      }

      .smm-richtext-node-wrap p {
        font-family: auto;
      }
      `,
        );
        let cssText = `
      .ql-editor {
        overflow: hidden;
        padding: 0;
        height: auto;
        line-height: normal;
        -webkit-user-select: text;
      }
      
      .ql-container {
        height: auto;
        font-size: inherit;
      }

      .ql-container.ql-snow {
        border: none;
      }

      .smm-richtext-node-edit-wrap p {
        font-family: auto;
      }
    `;
        this.styleEl = document.createElement('style');
        this.styleEl.type = 'text/css';
        this.styleEl.innerHTML = cssText;
        document.head.appendChild(this.styleEl);
    }

    // 处理选项参数
    initOpt() {
        if (
            this.pluginOpt.fontFamilyList &&
            Array.isArray(this.pluginOpt.fontFamilyList)
        ) {
            fontFamilyList = this.pluginOpt.fontFamilyList;
        }
        if (
            this.pluginOpt.fontSizeList &&
            Array.isArray(this.pluginOpt.fontSizeList)
        ) {
            fontSizeList = this.pluginOpt.fontSizeList;
        }
    }

    // 扩展quill编辑器
    extendQuill() {
        if (extended) {
            return;
        }
        extended = true;

        this.extendFont([]);

        // 扩展quill的字号列表
        const SizeAttributor = Quill.import('attributors/class/size');
        SizeAttributor.whitelist = fontSizeList;
        Quill.register(SizeAttributor, true);

        const SizeStyle = Quill.import('attributors/style/size');
        SizeStyle.whitelist = fontSizeList;
        Quill.register(SizeStyle, true);
    }

    // 扩展字体列表
    extendFont(list = [], cover = false) {
        fontFamilyList = cover ? [...list] : [...fontFamilyList, ...list];

        // 扩展quill的字体列表
        const FontAttributor = Quill.import('attributors/class/font');
        FontAttributor.whitelist = fontFamilyList;
        Quill.register(FontAttributor, true);

        const FontStyle = Quill.import('attributors/style/font');
        FontStyle.whitelist = fontFamilyList;
        Quill.register(FontStyle, true);
    }

    // 显示文本编辑控件
    showEditText({ node, rect, isInserting, isFromKeyDown, isFromScale }) {
        if (this.showTextEdit) {
            return;
        }
        let {
            richTextEditFakeInPlace,
            customInnerElsAppendTo,
            nodeTextEditZIndex,
            textAutoWrapWidth,
            selectTextOnEnterEditText,
            transformRichTextOnEnterEdit,
            openRealtimeRenderOnNodeTextEdit,
        } = this.mindMap.opt;
        textAutoWrapWidth = node.hasCustomWidth()
            ? node.customTextWidth
            : textAutoWrapWidth;
        this.node = node;
        this.isInserting = isInserting;
        if (!rect) rect = node._textData.node.node.getBoundingClientRect();
        if (!isFromScale) {
            this.mindMap.emit('before_show_text_edit');
        }
        this.mindMap.renderer.textEdit.registerTmpShortcut();
        // 原始宽高
        let g = node._textData.node;
        let originWidth = g.attr('data-width');
        let originHeight = g.attr('data-height');
        // 缩放值
        let scaleX = rect.width / originWidth;
        let scaleY = rect.height / originHeight;
        // 内边距
        let paddingX = this.textNodePaddingX;
        let paddingY = this.textNodePaddingY;
        if (richTextEditFakeInPlace) {
            let paddingValue = node.getPaddingVale();
            paddingX = paddingValue.paddingX;
            paddingY = paddingValue.paddingY;
        }
        if (!this.textEditNode) {
            this.textEditNode = document.createElement('div');
            this.textEditNode.classList.add('smm-richtext-node-edit-wrap');
            this.textEditNode.style.cssText = `
        position:fixed; 
        box-sizing: border-box; 
        ${
            openRealtimeRenderOnNodeTextEdit
                ? ''
                : 'box-shadow: 0 0 20px rgba(0,0,0,.5);'
        }
        outline: none; 
        word-break: break-all;
        padding: ${paddingY}px ${paddingX}px;
      `;
            this.textEditNode.addEventListener('click', (e) => {
                e.stopPropagation();
            });
            this.textEditNode.addEventListener('mousedown', (e) => {
                e.stopPropagation();
            });
            this.textEditNode.addEventListener('keydown', (e) => {
                if (
                    this.mindMap.renderer.textEdit.checkIsAutoEnterTextEditKey(
                        e,
                    )
                ) {
                    e.stopPropagation();
                }
            });
            const targetNode = customInnerElsAppendTo || document.body;
            targetNode.appendChild(this.textEditNode);
        }
        this.textEditNode.style.marginLeft = `-${paddingX * scaleX}px`;
        this.textEditNode.style.marginTop = `-${paddingY * scaleY}px`;
        this.textEditNode.style.zIndex = nodeTextEditZIndex;
        if (!openRealtimeRenderOnNodeTextEdit) {
            this.textEditNode.style.background =
                this.mindMap.renderer.textEdit.getBackground(node);
        }
        this.textEditNode.style.minWidth = originWidth + paddingX * 2 + 'px';
        this.textEditNode.style.minHeight = originHeight + 'px';
        this.textEditNode.style.left = rect.left + 'px';
        this.textEditNode.style.top = rect.top + 'px';
        this.textEditNode.style.display = 'block';
        this.textEditNode.style.maxWidth =
            textAutoWrapWidth + paddingX * 2 + 'px';
        this.textEditNode.style.transform = `scale(${scaleX}, ${scaleY})`;
        this.textEditNode.style.transformOrigin = 'left top';
        if (richTextEditFakeInPlace) {
            this.textEditNode.style.borderRadius =
                (node.style.merge('borderRadius') || 5) + 'px';
            if (node.style.merge('shape') == 'roundedRectangle') {
                this.textEditNode.style.borderRadius =
                    (node.height || 50) + 'px';
            }
        }
        // 节点文本内容
        let nodeText = node.getData('text');
        if (typeof transformRichTextOnEnterEdit === 'function') {
            nodeText = transformRichTextOnEnterEdit(nodeText);
        }
        // 是否是空文本
        const isEmptyText = isUndef(nodeText);
        // 是否是非空的非富文本
        const noneEmptyNoneRichText = !node.getData('richText') && !isEmptyText;
        // 如果是空文本，那么设置为丢失样式状态，否则输入不会带上样式
        if (isEmptyText) {
            this.lostStyle = true;
        }
        if (noneEmptyNoneRichText) {
            // 还不是富文本
            let text = String(nodeText).split(/\n/gim).join('<br>');
            let html = `<p>${text}</p>`;
            this.textEditNode.innerHTML = this.cacheEditingText || html;
        } else {
            // 已经是富文本
            this.textEditNode.innerHTML = this.cacheEditingText || nodeText;
        }
        this.initQuillEditor();
        document.querySelector('.ql-editor').style.minHeight =
            originHeight + 'px';
        this.showTextEdit = true;
        // 如果是刚创建的节点，那么默认全选，否则普通激活不全选，除非selectTextOnEnterEditText配置为true
        // 在selectTextOnEnterEditText时，如果是在keydown事件进入的节点编辑，也不需要全选
        this.focus(
            isInserting || (selectTextOnEnterEditText && !isFromKeyDown)
                ? 0
                : null,
        );
        if (noneEmptyNoneRichText) {
            // 如果是非富文本的情况，需要手动应用文本样式
            this.setTextStyleIfNotRichText(node);
        }
        this.cacheEditingText = '';
    }

    // 当openRealtimeRenderOnNodeTextEdit配置更新后需要更新编辑框样式
    onOpenRealtimeRenderOnNodeTextEditConfigUpdate(
        openRealtimeRenderOnNodeTextEdit,
    ) {
        if (!this.textEditNode) return;
        this.textEditNode.style.background = openRealtimeRenderOnNodeTextEdit
            ? 'transparent'
            : this.node
            ? this.mindMap.renderer.textEdit.getBackground(this.node)
            : '';
        this.textEditNode.style.boxShadow = openRealtimeRenderOnNodeTextEdit
            ? 'none'
            : '0 0 20px rgba(0,0,0,.5)';
    }

    // 更新文本编辑框的大小和位置
    updateTextEditNode() {
        if (!this.node) return;
        const g = this.node._textData.node;
        const rect = g.node.getBoundingClientRect();
        const originWidth = g.attr('data-width');
        const originHeight = g.attr('data-height');
        this.textEditNode.style.minWidth =
            originWidth + this.textNodePaddingX * 2 + 'px';
        this.textEditNode.style.minHeight = originHeight + 'px';
        this.textEditNode.style.left = rect.left + 'px';
        this.textEditNode.style.top = rect.top + 'px';
    }

    // 删除文本编辑框元素
    removeTextEditEl() {
        if (!this.textEditNode) return;
        const targetNode =
            this.mindMap.opt.customInnerElsAppendTo || document.body;
        targetNode.removeChild(this.textEditNode);
    }

    // 如果是非富文本的情况，需要手动应用文本样式
    setTextStyleIfNotRichText(node) {
        let style = {
            font: node.style.merge('fontFamily'),
            color: node.style.merge('color'),
            italic: node.style.merge('fontStyle') === 'italic',
            bold: node.style.merge('fontWeight') === 'bold',
            size: node.style.merge('fontSize') + 'px',
            underline: node.style.merge('textDecoration') === 'underline',
            strike: node.style.merge('textDecoration') === 'line-through',
        };
        this.pureFormatAllText(style);
    }

    // 获取当前正在编辑的内容
    getEditText() {
        let html = this.quill.container.firstChild.innerHTML;
        // 去除ql-cursor节点
        // https://github.com/wanglin2/mind-map/commit/138cc4b3e824671143f0bf70e5c46796f48520d0
        // https://github.com/wanglin2/mind-map/commit/0760500cebe8ec4e8ad84ab63f877b8b2a193aa1
        // html = removeHtmlNodeByClass(html, '.ql-cursor')
        // 去除最后的空行
        return html.replace(/<p><br><\/p>$/, '');
    }

    // 给html字符串中的节点样式按样式名首字母排序
    sortHtmlNodeStyles(html) {
        return html.replace(
            /(<[^<>]+\s+style=")([^"]+)("\s*>)/g,
            (_, a, b, c) => {
                let arr = b.match(/[^:]+:[^:]+;/g) || [];
                arr = arr.map((item) => {
                    return item.trim();
                });
                arr.sort();
                return a + arr.join('') + c;
            },
        );
    }

    // 隐藏文本编辑控件，即完成编辑
    hideEditText(nodes) {
        if (!this.showTextEdit) {
            return;
        }
        const { beforeHideRichTextEdit } = this.mindMap.opt;
        if (typeof beforeHideRichTextEdit === 'function') {
            beforeHideRichTextEdit(this);
        }
        let html = this.getEditText();
        html = this.sortHtmlNodeStyles(html);
        const list = nodes && nodes.length > 0 ? nodes : [this.node];
        const node = this.node;
        this.textEditNode.style.display = 'none';
        this.showTextEdit = false;
        this.mindMap.emit('rich_text_selection_change', false);
        this.node = null;
        this.isInserting = false;
        list.forEach((node) => {
            this.mindMap.execCommand('SET_NODE_TEXT', node, html, true);
            // if (node.isGeneralization) {
            // 概要节点
            // node.generalizationBelongNode.updateGeneralization()
            // }
            this.mindMap.render();
        });
        this.mindMap.emit('hide_text_edit', this.textEditNode, list, node);
    }

    // 初始化Quill富文本编辑器
    initQuillEditor() {
        this.quill = new Quill(this.textEditNode, {
            modules: {
                toolbar: false,
                keyboard: {
                    bindings: {
                        enter: {
                            key: 'Enter',
                            handler: function () {
                                // 覆盖默认的回车键，禁止换行
                            },
                        },
                        shiftEnter: {
                            key: 'Enter',
                            shiftKey: true,
                            handler: function (range, context) {
                                // 覆盖默认的换行，默认情况下新行的样式会丢失
                                const lineFormats = Object.keys(
                                    context.format,
                                ).reduce((formats, format) => {
                                    if (
                                        this.quill.scroll.query(
                                            format,
                                            Scope.BLOCK,
                                        ) &&
                                        !Array.isArray(context.format[format])
                                    ) {
                                        formats[format] =
                                            context.format[format];
                                    }
                                    return formats;
                                }, {});
                                const delta = new Delta()
                                    .retain(range.index)
                                    .delete(range.length)
                                    .insert('\n', lineFormats);
                                this.quill.updateContents(
                                    delta,
                                    Quill.sources.USER,
                                );
                                this.quill.setSelection(
                                    range.index + 1,
                                    Quill.sources.SILENT,
                                );
                                this.quill.focus();
                                Object.keys(context.format).forEach((name) => {
                                    if (lineFormats[name] != null) return;
                                    if (Array.isArray(context.format[name]))
                                        return;
                                    if (name === 'code' || name === 'link')
                                        return;
                                    this.quill.format(
                                        name,
                                        context.format[name],
                                        Quill.sources.USER,
                                    );
                                });
                            },
                        },
                        tab: {
                            key: 9,
                            handler: function () {
                                // 覆盖默认的tab键
                            },
                        },
                    },
                },
            },
            theme: 'snow',
        });
        // 拦截复制事件，即Ctrl + c，去除多余的空行
        this.quill.root.addEventListener('copy', (event) => {
            event.preventDefault();
            const sel = window.getSelection();
            const originStr = sel.toString();
            try {
                const range = sel.getRangeAt(0);
                const div = document.createElement('div');
                div.appendChild(range.cloneContents());
                const text = nodeRichTextToTextWithWrap(div.innerHTML);
                event.clipboardData.setData('text/plain', text);
            } catch (e) {
                event.clipboardData.setData('text/plain', originStr);
            }
        });
        this.quill.on('selection-change', (range) => {
            // 刚创建的节点全选不需要显示操作条
            if (this.isInserting) return;
            this.lastRange = this.range;
            this.range = null;
            if (range) {
                this.pasteUseRange = range;
                let bounds = this.quill.getBounds(range.index, range.length);
                let rect = this.textEditNode.getBoundingClientRect();
                let rectInfo = {
                    left: bounds.left + rect.left,
                    top: bounds.top + rect.top,
                    right: bounds.right + rect.left,
                    bottom: bounds.bottom + rect.top,
                    width: bounds.width,
                };
                let formatInfo = this.quill.getFormat(
                    range.index,
                    range.length,
                );
                let hasRange = false;
                if (range.length == 0) {
                    hasRange = false;
                } else {
                    this.range = range;
                    hasRange = true;
                }
                this.mindMap.emit(
                    'rich_text_selection_change',
                    hasRange,
                    rectInfo,
                    formatInfo,
                );
            } else {
                this.mindMap.emit(
                    'rich_text_selection_change',
                    false,
                    null,
                    null,
                );
            }
        });
        this.quill.on('text-change', () => {
            let contents = this.quill.getContents();
            let len = contents.ops.length;
            // 如果编辑过程中删除所有字符，那么会丢失主题的样式
            if (len <= 0 || (len === 1 && contents.ops[0].insert === '\n')) {
                this.lostStyle = true;
                // 需要删除节点的样式数据
                this.syncFormatToNodeConfig(null, true);
            } else if (this.lostStyle && !this.isCompositing) {
                // 如果处于样式丢失状态，那么需要进行格式化加回样式
                this.setTextStyleIfNotRichText(this.node);
                this.lostStyle = false;
            }
            this.mindMap.emit('node_text_edit_change', {
                node: this.node,
                text: this.getEditText(),
                richText: true,
            });
        });
        // 拦截粘贴，只允许粘贴纯文本
        // this.quill.clipboard.addMatcher(Node.TEXT_NODE, node => {
        //   let style = this.getPasteTextStyle()
        //   return new Delta().insert(this.formatPasteText(node.data), style)
        // })
        // 剪贴板里只要存在文本就会走这里，所以当剪贴板里是纯文本，或文本+图片都可以监听到和拦截，但是只有纯图片时不会走这里，所以无法拦截
        this.quill.clipboard.addMatcher(Node.ELEMENT_NODE, (node, delta) => {
            let ops = [];
            let style = this.getPasteTextStyle();
            delta.ops.forEach((op) => {
                // 过滤出文本内容，过滤掉换行
                if (op.insert && typeof op.insert === 'string') {
                    ops.push({
                        attributes: { ...style },
                        insert: this.formatPasteText(op.insert),
                    });
                }
            });
            delta.ops = ops;
            return delta;
        });
        // 拦截图片的粘贴，当剪贴板里是纯图片，或文本+图片都可以拦截到，但是带来的问题是文本+图片时里面的文本也无法粘贴
        this.quill.root.addEventListener(
            'paste',
            (e) => {
                if (
                    e.clipboardData &&
                    e.clipboardData.files &&
                    e.clipboardData.files.length
                ) {
                    e.preventDefault();
                }
            },
            true,
        );
    }

    // 获取粘贴的文本的样式
    getPasteTextStyle() {
        // 粘贴的数据使用当前光标位置处的文本样式
        if (this.pasteUseRange) {
            return this.quill.getFormat(
                this.pasteUseRange.index,
                this.pasteUseRange.length,
            );
        }
        return {};
    }

    // 处理粘贴的文本内容
    formatPasteText(text) {
        const { isSmm, data } = checkSmmFormatData(text);
        if (isSmm && data[0] && data[0].data) {
            // 只取第一个节点的纯文本
            return getTextFromHtml(data[0].data.text);
        } else {
            return text;
        }
    }

    // 正则输入中文
    onCompositionStart() {
        if (!this.showTextEdit) {
            return;
        }
        this.isCompositing = true;
    }

    // 中文输入中
    onCompositionUpdate() {
        if (!this.showTextEdit || !this.node) return;
        this.mindMap.emit('node_text_edit_change', {
            node: this.node,
            text: this.getEditText(),
            richText: true,
        });
    }

    // 中文输入结束
    onCompositionEnd() {
        if (!this.showTextEdit) {
            return;
        }
        this.isCompositing = false;
        if (!this.lostStyle) {
            return;
        }
        this.setTextStyleIfNotRichText(this.node);
    }

    // 选中全部
    selectAll() {
        this.quill.setSelection(0, this.quill.getLength());
    }

    // 聚焦
    focus(start) {
        let len = this.quill.getLength();
        this.quill.setSelection(typeof start === 'number' ? start : len, len);
    }

    // 格式化当前选中的文本
    formatText(config = {}, clear = false, pure = false) {
        if (!this.range && !this.lastRange) return;
        if (!pure) this.syncFormatToNodeConfig(config, clear);
        let rangeLost = !this.range;
        let range = rangeLost ? this.lastRange : this.range;
        clear
            ? this.quill.removeFormat(range.index, range.length)
            : this.quill.formatText(range.index, range.length, config);
        if (rangeLost) {
            this.quill.setSelection(
                this.lastRange.index,
                this.lastRange.length,
            );
        }
    }

    // 清除当前选中文本的样式
    removeFormat() {
        // 先移除全部样式
        this.formatText({}, true);
        // 再将样式恢复为当前主题改节点的默认样式
        const style = {};
        if (this.node) {
            [
                'fontFamily',
                'fontSize',
                'fontWeight',
                'fontStyle',
                'textDecoration',
                'color',
            ].forEach((key) => {
                style[key] = this.node.style.merge(key);
            });
        }
        const config = this.normalStyleToRichTextStyle(style);
        this.formatText(config, false, true);
    }

    // 格式化指定范围的文本
    formatRangeText(range, config = {}) {
        if (!range) return;
        this.syncFormatToNodeConfig(config);
        this.quill.formatText(range.index, range.length, config);
    }

    // 格式化所有文本
    formatAllText(config = {}) {
        this.syncFormatToNodeConfig(config);
        this.pureFormatAllText(config);
    }

    // 纯粹的格式化所有文本
    pureFormatAllText(config = {}) {
        this.quill.formatText(0, this.quill.getLength(), config);
    }

    // 同步格式化到节点样式配置
    syncFormatToNodeConfig(config, clear) {
        if (!this.node) return;
        if (clear) {
            // 清除文本样式
            [
                'fontFamily',
                'fontSize',
                'fontWeight',
                'fontStyle',
                'textDecoration',
                'color',
            ].forEach((prop) => {
                delete this.node.nodeData.data[prop];
            });
        } else {
            let data = this.richTextStyleToNormalStyle(config);
            this.mindMap.execCommand('SET_NODE_DATA', this.node, data);
        }
    }

    // 将普通节点样式对象转换成富文本样式对象
    normalStyleToRichTextStyle(style) {
        let config = {};
        Object.keys(style).forEach((prop) => {
            let value = style[prop];
            switch (prop) {
                case 'fontFamily':
                    config.font = value;
                    break;
                case 'fontSize':
                    config.size = value + 'px';
                    break;
                case 'fontWeight':
                    config.bold = value === 'bold';
                    break;
                case 'fontStyle':
                    config.italic = value === 'italic';
                    break;
                case 'textDecoration':
                    config.underline = value === 'underline';
                    config.strike = value === 'line-through';
                    break;
                case 'color':
                    config.color = value;
                    break;
                default:
                    break;
            }
        });
        return config;
    }

    // 将富文本样式对象转换成普通节点样式对象
    richTextStyleToNormalStyle(config) {
        let data = {};
        Object.keys(config).forEach((prop) => {
            let value = config[prop];
            switch (prop) {
                case 'font':
                    data.fontFamily = value;
                    break;
                case 'size':
                    data.fontSize = parseFloat(value);
                    break;
                case 'bold':
                    data.fontWeight = value ? 'bold' : 'normal';
                    break;
                case 'italic':
                    data.fontStyle = value ? 'italic' : 'normal';
                    break;
                case 'underline':
                    data.textDecoration = value ? 'underline' : 'none';
                    break;
                case 'strike':
                    data.textDecoration = value ? 'line-through' : 'none';
                    break;
                case 'color':
                    data.color = value;
                    break;
                default:
                    break;
            }
        });
        return data;
    }

    // 给未激活的节点设置富文本样式
    setNotActiveNodeStyle(node, style) {
        const config = this.normalStyleToRichTextStyle(style);
        if (Object.keys(config).length > 0) {
            this.showEditText({ node });
            this.formatAllText(config);
            this.hideEditText([node]);
        }
    }

    // 检查指定节点是否存在自定义的富文本样式
    checkNodeHasCustomRichTextStyle(node) {
        const list = [
            'fontFamily',
            'fontSize',
            'fontWeight',
            'fontStyle',
            'textDecoration',
            'color',
        ];
        const nodeData = node instanceof MindMapNode ? node.getData() : node;
        for (let i = 0; i < list.length; i++) {
            if (nodeData[list[i]] !== undefined) {
                return true;
            }
        }
        return false;
    }

    // 将所有节点转换成非富文本节点
    transformAllNodesToNormalNode() {
        if (!this.mindMap.renderer.renderTree) return;
        walk(
            this.mindMap.renderer.renderTree,
            null,
            (node) => {
                if (node.data.richText) {
                    node.data.richText = false;
                    node.data.text = getTextFromHtml(node.data.text);
                }
                // 概要
                if (node.data) {
                    const generalizationList = formatGetNodeGeneralization(
                        node.data,
                    );
                    generalizationList.forEach((item) => {
                        item.richText = false;
                        item.text = getTextFromHtml(item.text);
                    });
                }
            },
            null,
            true,
            0,
            0,
        );
        // 清空历史数据，并且触发数据变化
        this.mindMap.command.clearHistory();
        this.mindMap.command.addHistory();
        this.mindMap.render(null, CONSTANTS.TRANSFORM_TO_NORMAL_NODE);
    }

    // 处理导入数据
    handleSetData(data) {
        let walk = (root) => {
            if (root.data && !root.data.richText) {
                root.data.richText = true;
                root.data.resetRichText = true;
            }
            // 概要
            if (root.data) {
                const generalizationList = formatGetNodeGeneralization(
                    root.data,
                );
                generalizationList.forEach((item) => {
                    item.richText = true;
                    item.resetRichText = true;
                });
            }
            if (root.children && root.children.length > 0) {
                Array.from(root.children).forEach((item) => {
                    walk(item);
                });
            }
        };
        walk(data);
        return data;
    }

    // 插件被移除前做的事情
    beforePluginRemove() {
        this.transformAllNodesToNormalNode();
        document.head.removeChild(this.styleEl);
        this.unbindEvent();
        this.mindMap.removeAppendCss('richText');
    }

    // 插件被卸载前做的事情
    beforePluginDestroy() {
        document.head.removeChild(this.styleEl);
        this.unbindEvent();
    }
}

RichText.instanceName = 'richText';

export default RichText;
